Hello, everyone!
終於可以進入下個階段囉!被翻爛的書今天想用新的專案練習Active Record 基本的query methods,並嘗試用SQL methods 來呈現及比較用法。由於自己是SQL 魯蛇,因此要特別留心method 的形態、單複數、大小寫等,那就讓我們開始吧!
首先我們來試試看取出User.first.email
:
irb(main):021:0> User.first.email
User Load (0.6ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]]
"Sincere@april.biz"
這是Active Record 的data access method;可如果是利用SQL 可以怎麼寫呢?
我們先來組裝基本的語法:
SELECT * FROM users
# ↓
SELECT * FROM users WHERE id = 1
# ↓
SELECT email FROM users WHERE id = 1
我們試試看將SQL 丟到console 執行:
sql = "SELECT email FROM users WHERE id = 1"
# 目前查到了兩個比較適合的語法:
# 方法1
irb(main):031:0> ActiveRecord::Base.connection.exec_query(sql).rows
SQL (0.7ms) SELECT email FROM users WHERE id = 1
[
[0] [
[0] "Sincere@april.biz"
]
]
# 方法2
irb(main):032:0> User.find_by_sql(sql)
User Load (0.7ms) SELECT email FROM users WHERE id = 1
[
[0] #<User:0x00007f94196c2fa0> {
"id" => nil,
"email" => "Sincere@april.biz"
}
]
先稍微觀察、研究這兩個方法回傳的形態是什麼:
irb(main):042:0> ActiveRecord::Base.connection.exec_query(sql).class
SQL (0.8ms) SELECT email FROM users WHERE id = 1
ActiveRecord::Result < Object
irb(main):044:0> User.find_by_sql(sql).class
User Load (0.9ms) SELECT email FROM users WHERE id = 1
Array < Object
有點混亂,但我們先查查第一個方法是來自哪(ActiveRecord::Base.connection.exec_query
);
接著會看到一個很熟悉的字眼ActiveRecord::Base
,這不是在app/models/application_record.rb
出現過嗎:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end
進去看了一下才發現有這東西:
下方的文字說明也在Rails Guide 看到,雖然水好像很深;之後再沿線搜尋,會找到這是個Active Record 的module ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements
Public Instance Methods
看起來是用丟SQL 語法進去,回傳一個處理後的ActiveRecord::Result
XD
而ActiveRecord::Result
又是什麼呢:This class encapsulates a result returned from calling #exec_query on any database connection adapter.
是個會處理及回傳封裝後結果的類別
再去看看他的initialize
方法:
def initialize(columns, rows, column_types = {})
@columns = columns
@rows = rows
@hash_rows = nil
@column_types = column_types
end
大概是將SQL 處理的結果根據資料表的欄、列回傳個hash 吧 XD
整理一下,ActiveRecord::Base.connection.exec_query(sql) 應該是:
嗯... 好像有看沒有懂,且回傳的結果有點雜,自己沒有很喜歡...
但,明天再繼續研究第二個方法User.find_by_sql(sql)
的由來好了 XD
今天的研究就到這結束吧,謝謝大家~